/*************************************************************************
 *                                                                       *
 * This file is part of the FreeMAPs distribution.  For full copyright   *
 * information, see COPYRIGHT and COPYING.LESSER.                        *
 *                                                                       *
 * Author:           sqbang                                              *
 * Email:            sqbang@ustc.edu                                     *
 * Date:             2013.12.10                                          *
 * Acknowledgements: This file is a copy from SAMRAI projection          *
 *                   with slight modification.                           *
 *                                                                       *
 *************************************************************************/

#ifndef FreeMAPs_include_COMMON_tbox_InputManager_h
#define FreeMAPs_include_COMMON_tbox_InputManager_h

#include "FreeMAPsConfig.h"

//COMMON headers
#include "COMMON/tbox/InputDatabase.h"
#include "COMMON/tbox/StartupShutdownManager.h"

namespace FreeMAPs
{

/**
 * Class InputManager parses an input file and returns the associated
 * database.  This manager class hides the complexity of opening the
 * input file, creating the parser, and populating the database with
 * values.  The input manager is simple enough that it did not need
 * to be implemented as a singleton class; however, it was implemented
 * as a singleton to be consistent with the restart manager class.
 *
 * All processors must call the parsing routines.  Any errors are reported
 * to pout and will result in termination of the program.
 *
 * The input file will generally have the following format.  For each
 * object that requires user specified input, an entry of the following
 * format should be included in the input file.
 *
 * \verbatim
 * Object_entry {
 *    keyword1 = <value1>     // maybe some end line comments
 *    keyword2 = <value2>
 *    nested_input_keyword {
 *       nested_data_keyword1 = <value1>
 *    }
 *     \ldots
 * }
 * \endverbatim
 *
 * For convenience, the input parser also supports C/C++ style comments,
 * "include" files, and some expression evaluation.
 *
 */
class InputManager
{
protected:

    /**
     * The constructor is protected, since only subclasses of the singleton
     * may access the constructor.  Others may not explicitly create a
     * singleton class.
     */
    InputManager();

    /**
     * The destructor for the input manager is protected, since only the
     * singleton class and subclasses may destroy the manager objects.
     */
    ~InputManager();

public:

    /**
     * Return a pointer to the single instance of the input manager.
     * All access to the input manager object is through get_manager().
     *
     * usually in COMMON, the get_instance() used instead of get_manager(),
     * but for consistent to the SAMRAI, use get_manager()
     */
    static InputManager*
    get_manager();

    /**
     * Set a new input manager.  This routine can only be used by subclasses
     * since the constructor and destructor are protected.  The manager object
     * will be deleted at program exit.
     */
    static void
    set_manager(
        InputManager* manager);

    /**
     * Return whether or not the manager has read an input database.  If
     * so, it returns true.  If not, false.
     */
    static inline bool
    is_input_database_exists();

    /**
     * Accessor method for the root input database held by InputManager.
     * Inputs are read from the input file and held in this database.
     * This method returns a pointer to the database, allowing any class
     * in SAMRAI to access the information inside it using standard
     * database calls.  For example, the following could appear in a
     * SAMRAI class:
     *
     *       // get root database
     *       const boost::shared_ptr<SAMRAI::tbox::Database> root_db =
     *          InputManager::get_manager()->get_input_database();
     *       // get class's sub-database
     *       const boost::shared_ptr<SAMRAI::tbox::Database> class_db =
     *          root_db->get_database("MyClass");
     *       // get parameter(s) from sub-database
     *       int dummy = class_db->get_integer("dummy");
     *
     *
     * where "dummy" was supplied in "MyClass" entry of the input file:
     *
     *       MyClass {
     *          dummy = ...
     *       }
     *
     * This function is intended for SAMRAI classes in which there is no
     * easy or efficient way to supply input parameters.
     */
    static inline const InputDatabase*
    get_input_database();

    /**
     * Create a new database named "main" from the specified input file.
     */
    const InputDatabase*
    parse_input_file(
        const std::string& file_name,
        bool& parse_ok);

    /**
     * Parse data from the specified file into the existing database.
     */
    bool
    parse_input_file(
        const std::string& file_name,
        InputDatabase* input_db);

    /*
     * Deallocate the input manager instance.  It is not necessary to call
     * this routine at program termination, since it is automatically called
     * by the SAMRAI shutdown routines.
     */
    static void
    finalize_callback();
private:

    static InputManager* s_instance;

    static StartupShutdownManager::Handler s_finalize_handler;

    static InputDatabase* s_input_db;

private:

    DISALLOW_COPY_AND_ASSIGN (InputManager);
};

}

#include "COMMON/tbox/InputManager.inl"

#endif
